using System.Diagnostics;

namespace ThingsGateway.Foundation
{
    /// <summary>
    /// 依赖项属性
    /// </summary>
    [DebuggerDisplay("Name={Name},Type={ValueType}")]
    public class DependencyProperty
    {
        #region Protected Fields

        /// <summary>
        /// 属性名称
        /// </summary>
        protected string m_name;
        /// <summary>
        /// 描述
        /// </summary>
        protected string m_description;
        /// <summary>
        /// 所属类型
        /// </summary>
        protected Type m_owner;

        /// <summary>
        /// 值类型
        /// </summary>
        protected Type m_valueType;

        #endregion Protected Fields

        #region Private Fields

        private object m_value;

        #endregion Private Fields

        #region Private Constructors

        /// <summary>
        /// 依赖项属性
        /// </summary>
        private DependencyProperty()
        {
        }

        #endregion Private Constructors

        #region Public Properties

        /// <summary>
        /// 默认值
        /// </summary>
        public object DefauleValue => m_value;
        /// <summary>
        /// 描述
        /// </summary>
        public string Description => m_description;
        /// <summary>
        /// 属性名
        /// </summary>
        public string Name => m_name;

        /// <summary>
        /// 所属类型
        /// </summary>
        public Type Owner => m_owner;

        /// <summary>
        /// 值类型
        /// </summary>
        public Type ValueType => m_valueType;

        #endregion Public Properties


        #region Public Methods

        /// <summary>
        /// 注册依赖项属性。
        /// <para>依赖属性的默认值，可能会应用于所有的<see cref="IDependencyObject"/></para>
        /// </summary>
        /// <param name="propertyName"></param>
        /// <param name="valueType"></param>
        /// <param name="owner"></param>
        /// <param name="value">依赖项属性值，一般该值应该是值类型，因为它可能会被用于多个依赖对象。</param>
        /// <returns></returns>
        public static DependencyProperty Register(string propertyName, Type valueType, Type owner, object value, string description = "")
        {
            DependencyProperty dp = new DependencyProperty
            {
                m_name = propertyName,
                m_valueType = valueType,
                m_owner = owner,
                m_description = description,
            };
            dp.SetDefauleValue(value);
            return dp;
        }

        #endregion Public Methods

        #region Internal Methods

        internal void DataValidation(object value)
        {
            if (value == null)
            {
                if (typeof(ValueType).IsAssignableFrom(m_valueType))
                {
                    throw new Exception($"属性“{m_name}”赋值类型不允许出现Null");
                }
            }
            else if (!m_valueType.IsAssignableFrom(value.GetType()))
            {
                throw new Exception($"属性“{m_name}”赋值类型与注册类型不一致，应当注入“{m_valueType}”类型");
            }
        }

        internal void SetDefauleValue(object value)
        {
            DataValidation(value);
            m_value = value;
        }

        #endregion Internal Methods
    }
}